﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using UT3Bots.UTItems;
using UT3Bots.Communications;
using System.Diagnostics;

namespace UT3Bots
{
	public class BotCommands
	{
		private UTBot _utBot;
		private UT3Connection _utConnection;

        public String LastCommandSent
        {
            get
            {
                return _utConnection.LastCommandSent;
            }
        }

        public String LastMessageReceived
        {
            get
            {
                return _utConnection.LastMessageReceived;
            }
        }

		public BotCommands(UTBot Bot, UT3Connection Connection)
		{
			this._utBot = Bot;
			this._utConnection = Connection;
		}

		/// <summary>
		/// Command your bot to shoot in the direction it is facing
		/// </summary>
		/// <param name="useSecondaryFire">True if you want to use the Alternative Fire of your current gun instead of its primary fire</param>
		public void StartFiring(bool useSecondaryFire)
		{
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.FIRE, "None", useSecondaryFire.ToString()));
		}

		/// <summary>
		/// Command your bot to shoot at a specific location
		/// </summary>
		/// <param name="Location">The location to fire at</param>
		/// <param name="useSecondaryFire">True if you want to use the Alternative Fire of your current gun instead of its primary fire</param>
		public void StartFiring(UTVector Location, bool useSecondaryFire)
		{
            if (Location != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.FIRE, Location.ToString(), useSecondaryFire.ToString()));
		}

		/// <summary>
		/// Command your bot to shoot at a specific target
		/// </summary>
		/// <param name="Target">The target to fire at</param>
		/// <param name="useSecondaryFire">True if you want to use the Alternative Fire of your current gun instead of its primary fire</param>
		public void StartFiring(UTIdentifier Target, bool useSecondaryFire)
		{
            if (Target != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.FIRE, Target.ToString(), useSecondaryFire.ToString()));
		}

		/// <summary>
		/// Command your bot to stop shooting
		/// </summary>
		public void StopFiring()
		{
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.STOP_FIRE));
		}

		/// <summary>
		/// Command your bot to stop moving
		/// </summary>
		public void StopMoving()
		{
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.STOP));
		}

		/// <summary>
		/// Command your bot to jump
		/// </summary>
		public void Jump()
		{
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.JUMP));
		}

		/// <summary>
		/// Command your bot to automatically turn towards and move directly to the destination
		/// </summary>
		/// <param name="Location">The location you want to go to (The location must be visible to you when the command is recieved or your bot will do nothing.)</param>
		public void RunTo(UTVector Location)
		{
            if(Location != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.RUN_TO, "0.0", "0.0", Location.ToString()));
		}

		/// <summary>
		/// Command your bot to automatically turn towards and move directly to the destination
		/// </summary>
		/// <param name="Target">The target you want to go to (The object must be visible to you when the command is recieved or your bot will do nothing.)</param>
		public void RunTo(UTIdentifier Target)
		{
            if (Target != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.RUN_TO, "0.0", "0.0", Target.ToString()));
		}

		/// <summary>
		/// Command your bot to move towards a destination while facing another object
		/// </summary>
		/// <param name="Location">The location that you want to move to</param>
		/// <param name="Target">The object you want to face while moving  (The object must be visible to you when the command is recieved or your bot will do nothing.)</param>
		public void StrafeTo(UTVector Location, UTIdentifier Target)
		{
            if (Target != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.STRAFE_TO, Location.ToString(), Target.ToString()));
		}

		/// <summary>
		/// Command your bot to move towards a destination while facing another location
		/// </summary>
		/// <param name="Location">The location that you want to move to</param>
		/// <param name="Target">The target you want to face while moving  (The target must be visible to you when the command is recieved or your bot will do nothing.)</param>
		public void StrafeTo(UTVector Location, UTVector Target)
		{
            if (Target != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.STRAFE_TO, Location.ToString(), Target.ToString()));
		}


		/// <summary>
		/// Command your bot to turn to face a specified location
		/// </summary>
		/// <param name="Location">The location you want to turn to</param>
		public void RotateTo(UTVector Location)
		{
            if (Location != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.ROTATE_TO, Location.ToString(), "Location"));
		}

		/// <summary>
		/// Command your bot to turn to face a specified object
		/// </summary>
		/// <param name="Target">The object you want to turn to</param>
		public void RotateTo(UTIdentifier Target)
		{
            if (Target != null)
			    this._utConnection.SendLine(Message.BuildMessage(CommandMessage.ROTATE_TO, Target.ToString(), "Target"));
		}

		/// <summary>
		/// Command your bot to turn to face a specified angle
		/// </summary>
		/// <param name="Target">The angle you want to turn to in degrees</param>
		public void RotateTo(int Degrees)
		{
			//(2pi = 65535 UT units)
			Degrees = Degrees % 360;
			int units = (int)((Degrees / 360d) * 65535);
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.ROTATE_TO, units.ToString(), "Rotation"));
		}

		/// <summary>
		/// Command your bot to turn a specified amount
		/// </summary>
		/// <param name="Degrees">The number of degrees your want to turn from where you are facing at the moment</param>
		public void RotateBy(int Degrees)
		{
			//(2pi = 65535 UT units)
			Degrees = Degrees % 360;
			int units = (int)((Degrees / 360d) * 65535);
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.ROTATE_BY, units.ToString(), "Horizontal"));
		}

		/// <summary>
		/// Send a chat message to the server
		/// </summary>
		/// <param name="Message">The message you want to send</param>
		/// <param name="SendToTeam">True if you want to only send this to your team</param>
		public void SendChatMessage(string Message, bool SendToTeam)
		{
			Message = Message.Replace("\n", " ");
			Message = Message.Replace("\r", " ");
			Message = Message.Replace("|", " ");
			this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.SENDCHAT, Message, SendToTeam ? "Team" : "Global"));
		}

		/// <summary>
		/// Taunt a player with the built in voice taunts
		/// </summary>
		/// <param name="Target">The ID of the player you want to taunt (this must be a valid player, or nothing will happen)</param>
		public void SendTauntMessage(UTIdentifier Target)
		{
			if (Target != null)
			{
				this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.SENDTAUNT, Target.ToString()));
			}
		}

		/// <summary>
		/// Just killed someone? Why not taunt them with some fetching pelvic thrusts!
		/// </summary>
		/// <param name="Emote">The emote you want to send</param>
		public void PerformEmote(Emote Emote)
		{
			this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.SENDEMOTE, Emote.GetStringValue()));
		}

		/// <summary>
		/// Set whether you are walking or running (default is run). 
		/// Walking means you move at about 1/3 normal speed, make less noise, and won't fall off ledges
		/// </summary>
		/// <param name="UseWalk">Send True to go into walk mode or False to go into run mode</param>
		public void SetMovingSpeed(bool UseWalk)
		{
			this._utConnection.SendLine(Message.BuildMessage(CommandMessage.SETWALK, UseWalk.ToString()));
		}

		/// <summary>
		/// Command your bot to change to its most powerful weapon
		/// </summary>
		public void ChangeWeapon()
		{
			this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.CHANGE_WEAPON, "BEST"));
		}

		/// <summary>
		/// Command your bot to change to a specific weapon 
		/// The weapon will be changed if you have this weapon in your inventory and it has ammo left
		/// </summary>
		/// <param name="Weapon">The Weapon ID you want to switch to</param>
		public void ChangeWeapon(WeaponType wt)
		{
            string wtClass = "UTWeap_ImpactHammer";
            switch (wt)
	        {
		        case WeaponType.ImpactHammer:
                    wtClass = "UTWeap_ImpactHammer";
                 break;
                case WeaponType.Enforcer:
                    wtClass = "UTWeap_Enforcer";
                 break;
                case WeaponType.BioRifle:
                    wtClass = "UTWeap_BioRifle_Content";
                 break;
                case WeaponType.ShockRifle:
                    wtClass = "UTWeap_ShockRifle";
                 break;
                case WeaponType.Stinger:
                    wtClass = "UTWeap_Stinger";
                 break;
                case WeaponType.Avril:
                    wtClass = "UTWeap_Avril";
                 break;
                case WeaponType.FlakCannon:
                    wtClass = "UTWeap_FlakCannon";
                 break;
                case WeaponType.SniperRifle:
                    wtClass = "UTWeap_SniperRifle";
                 break;
                case WeaponType.RocketLauncher:
                    wtClass = "UTWeap_RocketLauncher";
                 break;
                case WeaponType.Redeemer:
                    wtClass = "UTWeap_Redeemer";
                 break;
                case WeaponType.InstaGibRifle:
                    wtClass = "UTWeap_InstagibRifle";
                 break;
                default:
                 break;
	        }
			this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.CHANGE_WEAPON,wtClass));
		}


		/// <summary>
		/// Get a path to a specified target. 
		/// An ordered list of nay points will be returned to you via the OnPathReceived() event that you should attach to
		/// </summary>
		/// <param name="Id">A message ID made up by you and echoed in respose so you can match up response with query</param>
		/// <param name="Target">The target you would like to go to</param>
		public void GetPath(string Id, UTIdentifier Target)
		{
			if (Target != null)
			{
				this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.GET_PATH, Id, Target.ToString()));
			}
		}

		/// <summary>
		/// Get a path to a specified location. 
		/// An ordered list of nay points will be returned to you via the OnPathReceived() event that you should attach to
		/// </summary>
		/// <param name="Id">A message ID made up by you and echoed in respose so you can match up response with query</param>
		/// <param name="Location">The location you would like to go to</param>
		public void GetPath(string Id, UTVector Location)
		{
            if (Location != null)
            {
                this._utConnection.SendLine(Communications.Message.BuildMessage(CommandMessage.GET_PATH, Id, Location.ToString()));
            }
		}



	}
}
